<template>
  <view
    class="calender padding-sm shadow bg-white"
    @touchmove.stop="transformShape"
    @touchstart.stop="transformStart"
    @touchend.stop="transformEnd"
    v-if="show"
    :style="{
      opacity: show ? '1' : '0',
      transition: 'opacity 0.3s ease-in-out',
      width: '100%',
      overflow: 'hidden',
      position: 'relative',
    }"
  >
    <view class="flex justify-between padding-sm">
      <!-- 上一周 -->
      <text class="cuIcon-back" @click="preWeek"></text>
      <view class="text-bold flex-sub flex">
        <text class="flex-sub text-center">
          {{ currentDate.format("YYYY-MM") }}/第{{ currentDate.week() }}周
        </text>
        <view class="flex-sub text-center">
          <text>星期{{ WEEK_MAP[selectedDate.format("dddd")] }}</text>
          <text class="cuIcon-refresh" @click="reset"></text>
        </view>
      </view>

      <!-- 下一周 -->
      <text class="cuIcon-right" @click="nextWeek"></text>
    </view>
    <view class="calendar-header grid col-7" id="header">
      <view
        class="text-center text-bold"
        :key="item"
        v-for="item in ['一', '二', '三', '四', '五', '六', '日']"
        >{{ item }}
      </view>
    </view>
    <view
      class="swiper"
      :style="{
        height: mode == 'month' ? 85 * 5 + 'rpx' : 85 + 'rpx',
        transform: `translateX(${current * 750}rpx)`,
      }"
      @touchmove="transformSwiper"
      @touchstart="transformSwiperStart"
      @touchend="transformSwiperEnd"
    >
      <view
        v-for="(itemss, index) in unKunowww"
        :key="itemss.id"
        :item-id="itemss.id"
        class="swiper-item"
        :style="{ transform: `translateX(${itemss.current * 750}rpx)` }"
      >
        <view
          class="calendar-body grid col-7"
          :style="{
            marginTop: marginTop + 'rpx',
            height: height ? height + 'rpx' : 'auto',
          }"
        >
          <view
            v-if="mode == 'month'"
            class="text-center padding-sm"
            :style="{ color: 'red' }"
            v-for="item in itemss.disabledBefore"
            :key="moment(item).format('YYYY-MM-DD')"
            @click="() => changePage(-1)"
            >{{ moment(item).date() }}
          </view>
          <view
            class="text-center padding-sm text-bold calendar-item"
            :class="{
              ranged:
                selectedMode &&
                startDate &&
                endDate &&
                moment(item).isBetween(
                  startDate.format('YYYY-MM-DD'),
                  endDate.format('YYYY-MM-DD'),
                  'day',
                  '[]'
                ),
              start: selectedMode&&startDate && item == startDate.format('YYYY-MM-DD'),
              end: selectedMode&&endDate && item == endDate.format('YYYY-MM-DD'),
            }"
            v-for="(item, index) in itemss.realDisplayInScreenData"
            @click="() => changePage(moment(item))"
            :key="moment(item).format('YYYY-MM-DD')"
          >
            <text
              :style="{
                borderRadius: '5px',
                padding: moment(item).date() > 10 ? '5px' : '8px',
                paddingTop: '5px',
                paddingBottom: '5px',
              }"
              :class="{
                selected:
                  moment(item).format('YYYY-MM-DD') ===
                  selectedDate.format('YYYY-MM-DD'),
                today:
                  moment(item).format('YYYY-MM-DD') ===
                  currentDate.format('YYYY-MM-DD'),
              }"
              >{{ moment(item).date() }}</text
            >
            <view
              class="point"
              v-if="checkIfShow(item)"
              :style="{ backgroundColor: markerColor(item) }"
            ></view>
          </view>
          <view
            v-if="mode == 'month'"
            class="text-center padding-sm"
            :style="{ color: 'red' }"
            v-for="item in itemss.disabledAfter"
            :key="moment(item).format('YYYY-MM-DD')"
            @click="() => changePage(-1)"
            >{{ moment(item).date() }}
          </view>
        </view>
      </view>
    </view>
    <view>
      <view>
        <text
          class="btn btn-primary square cuIcon-close bg-blue padding-xs"
          style="position: absolute; left: 10rpx; bottom: 5rpx"
          @click="handleClose"
          ></text
        >
        <text
          class="btn btn-primary square cuIcon-add bg-blue padding-xs"
          style="position: absolute; right: 10rpx; bottom: 5rpx"
          @click="handleOk"
          >确定</text
        >
      </view>
    </view>

    <image
      :src="mode == 'week' ? '/static/pulldown.png' : '/static/pullup.png'"
      mode="scaleToFill"
      style="width: 30rpx; height: 30rpx; display: block; margin: 0 auto"
    />
  </view>
</template>

<script>


// 新增自定义事件
/**
 * 1. 选择range完毕
 * 2.取消range选择
 * 3.日历模式：区间选择日历和普通单选日历
 * 4. 区间选择时 selectdate不变，只改变selectedMode为true，startDate和endDate变化
 *     单选时，只修改selectedDate， startDate和endDate永久为0
 * 
 */
const WEEK_MAP = {
  Monday: "一",
  Tuesday: "二",
  Wednesday: "三",
  Thursday: "四",
  Friday: "五",
  Saturday: "六",
  Sunday: "日",
};

export default {
  name: "calender",
  model: {
    prop: "value", // 对应 props msg
    event: "change",
  },
  props: {
    markers: {
      type: Array,
      default: () => [],
    },
    value: {
      type: Object,
    },
  },
  data() {
    return {
      title: "Hello",
      CustomBar: this.CustomBar,
      currentWeek: [],
      currentMonth: [],
      realDisplayInScreenData: [],
      disabledBefore: [],
      disabledAfter: [],

      preRealDisplayInScreenData: [],
      preDisabledBefore: [],
      preDisabledAfter: [],

      nextRealDisplayInScreenData: [],
      nextDisabledBefore: [],
      nextDisabledAfter: [],
      position: {
        start: 0,
        end: 0,
        swiperStart: 0,
        swiperEnd: 0,
      },
      show: false,
      currentDate: null, // 今天
      mode: "week", // 日历模式
      marginTop: 0,
      height: undefined,
      unKunowww: [],
      current: 0,
      selectedDate: this.moment(),
      WEEK_MAP,
      startDate: null,
      endDate: null,
      startOfWeek: this.moment().startOf("isoWeek"),
      endOfWeek: this.moment().endOf("isoWeek"),
      selectedMode: false,
    };
  },
  watch: {
    selectedDate(n) {
      // console.log("重置"); // 等月或周切换才需要currentDate重置？ currentDate始终跟着selectedDate
      // this.currentDate = this.selectedDate;
      console.log(n.format("YYYY-MM-DD"), "watch");
    },
    value: {
      handler(val) {
        // console.log(val.format("YYYY-MM-DD"), "watch");
        // this.selectedDate = val;
      },
      deep: true,
      immediate: true,
    },
  },
  created() {
    // console.log("星期几:" + this.moment().day());
    // console.log("第几周:" + this.moment().week());
    // console.log("当前日期" + this.moment().date(31).format("YYYY-MM-DD"));
    // console.log("几月份" + this.moment().month());
    // console.log("年份" + this.moment().year());
    // console.log("星期几本地" + this.moment().isoWeekday(1).date());
    // // console.log("几点了" + this.moment().hour());
    // // console.log("几号了:" + this.moment().day(0).date());
    // console.log("week year" + this.moment().weekYear());
    // console.log(
    //   "获取第几周的周日moment实力实例" +
    //     this.moment().local().isoWeek(24).date()
    // );

    // console.log(this.startDate.format("YYYY-MM-DD"), "startDate");
    // console.log(this.endDate.format("YYYY-MM-DD"), "endDate");
    console.log(this.startOfWeek.format("YYYY-MM-DD"), "startOfWeek");
    console.log(this.endOfWeek.format("YYYY-MM-DD"), "endOfWeek");
    this.currentDate = this.moment();

    this.initPage();
  },
  methods: {
    initPage() {
      // this.currentDate = this.selectedDate; // 不对 selectedDate要与外部绑定，所以不能把currentDate与selectedDate绑定
      this.getCurrentWeeks();
      this.getPreWeeks();
      this.getNextWeeks();
      console.log(this.unKunowww);
      this.$forceUpdate();
      //   this.getCurrentMonth();
    },
    getCurrentWeeks(flag) {
      let array = new Array(7).fill("0");
      this.currentWeek = array.map((item, index) => {
        return this.moment(this.currentDate.format("YYYY-MM-DD"))
          .isoWeekday(index + 1)
          .format("YYYY-MM-DD");
      });
      this.realDisplayInScreenData = this.currentWeek;
      this.unKunowww.push({
        realDisplayInScreenData: this.currentWeek,
        id: this.currentWeek[0],
        current: flag ? flag : 0,
      });

      //   当保存周日期的最后一个日期月份大于currentMonthIndex时候,月份改变
    },
    getPreWeeks(flag) {
      let array = new Array(7).fill("0");
      let currentWeek = array.map((item, index) => {
        return this.moment(this.currentDate)
          .subtract(1, "weeks")
          .isoWeekday(index + 1)
          .format("YYYY-MM-DD");
      });
      this.preRealDisplayInScreenData = currentWeek;
      if (
        this.unKunowww.findIndex((item) => item.id === currentWeek[0]) === -1
      ) {
        let lastCurrentIndex = this.unKunowww[0].current;
        this.unKunowww.unshift({
          realDisplayInScreenData: currentWeek,
          id: currentWeek[0],
          current: flag ? flag : lastCurrentIndex - 1,
        });
      }
    },
    getNextWeeks(flag) {
      let array = new Array(7).fill("0");
      let currentWeek = array.map((item, index) => {
        return this.moment(this.currentDate)
          .add(1, "weeks")
          .isoWeekday(index + 1)
          .format("YYYY-MM-DD");
      });
      this.nextRealDisplayInScreenData = currentWeek;
      if (
        this.unKunowww.findIndex((item) => item.id === currentWeek[0]) === -1
      ) {
        let lastCurrentIndex =
          this.unKunowww[this.unKunowww.length - 1].current;
        this.unKunowww.push({
          realDisplayInScreenData: currentWeek,
          id: currentWeek[0],
          current: flag ? flag : lastCurrentIndex + 1,
        });
      }
    },
    // 根据当前月份获取渲染月日历所需数据
    getCurrentMonth(flag) {
      let currentMonth = this.moment(this.currentDate).date(1);
      let daysOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).daysInMonth();

      let days = [];

      for (let i = 1; i <= daysOfMonth; i++) {
        // days.push(moment.date(i).format("YYYY-MM-DD"));
        let item = this.moment(currentMonth.format("YYYY-MM"), "YYYY-MM")
          .date(i)
          .format("YYYY-MM-DD");
        days.push(item);
        // console.log(currentMonth.date(i).format("YYYY-MM-DD"));
      }
      this.currentMonth = days;
      this.realDisplayInScreenData = this.currentMonth;

      let firstDayOfMonth = this.moment(
        this.currentDate.format("YYYY-MM"),
        "YYYY-MM"
      ).date(1);
      let firstDayWeekDayOfMonth = firstDayOfMonth.isoWeekday();

      //   将本月1日前面的日期补充到数组中
      this.disabledBefore = [];
      for (let i = 1; i < firstDayWeekDayOfMonth; i++) {
        let disabledDate = this.moment(firstDayOfMonth.format("YYYY-MM-DD"))
          .subtract(i, "days")
          .format("YYYY-MM-DD");
        this.disabledBefore.unshift(disabledDate);
      }

      //   将本月最后一天的日期补充到数组中

      let lastDayOfMonth = this.moment(
        this.currentDate.format("YYYY-MM"),
        "YYYY-MM"
      ).date(daysOfMonth);
      let lastDayWeekDayOfMonth = lastDayOfMonth.isoWeekday();
      this.disabledAfter = [];
      if (lastDayWeekDayOfMonth != 7) {
        for (let i = lastDayWeekDayOfMonth + 1; i <= 7; i++) {
          let disabledDate = this.moment(lastDayOfMonth.format("YYYY-MM-DD"))
            .isoWeekday(i, "days")
            .format("YYYY-MM-DD");
          this.disabledAfter.push(disabledDate);
        }
      }

      this.unKunowww.push({
        realDisplayInScreenData: this.currentMonth,
        id: this.currentMonth[0],
        current: flag ? flag : 0,
        disabledAfter: this.disabledAfter,
        disabledBefore: this.disabledBefore,
      });
    },
    getPreMonth(flag) {
      let currentMonth = this.moment(this.currentDate)
        .subtract(1, "months")
        .date(1);
      let daysOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).daysInMonth();

      let days = [];

      for (let i = 1; i <= daysOfMonth; i++) {
        // days.push(moment.date(i).format("YYYY-MM-DD"));
        let item = this.moment(currentMonth.format("YYYY-MM"), "YYYY-MM")
          .date(i)
          .format("YYYY-MM-DD");
        days.push(item);
        // console.log(currentMonth.date(i).format("YYYY-MM-DD"));
      }
      this.currentMonth = days;
      this.realDisplayInScreenData = this.currentMonth;

      let firstDayOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).date(1);
      let firstDayWeekDayOfMonth = firstDayOfMonth.isoWeekday();

      //   将本月1日前面的日期补充到数组中
      this.disabledBefore = [];
      for (let i = 1; i < firstDayWeekDayOfMonth; i++) {
        let disabledDate = this.moment(firstDayOfMonth.format("YYYY-MM-DD"))
          .subtract(i, "days")
          .format("YYYY-MM-DD");
        this.disabledBefore.unshift(disabledDate);
      }

      //   将本月最后一天的日期补充到数组中

      let lastDayOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).date(daysOfMonth);
      let lastDayWeekDayOfMonth = lastDayOfMonth.isoWeekday();
      this.disabledAfter = [];
      if (lastDayWeekDayOfMonth != 7) {
        for (let i = lastDayWeekDayOfMonth + 1; i <= 7; i++) {
          let disabledDate = this.moment(lastDayOfMonth.format("YYYY-MM-DD"))
            .isoWeekday(i, "days")
            .format("YYYY-MM-DD");
          this.disabledAfter.push(disabledDate);
        }
      }

      if (
        this.unKunowww.findIndex((item) => item.id === this.currentMonth[0]) ===
        -1
      ) {
        let lastCurrentIndex = this.unKunowww[0].current;

        this.unKunowww.unshift({
          realDisplayInScreenData: this.currentMonth,
          id: this.currentMonth[0],
          current: flag ? flag : lastCurrentIndex - 1,
          disabledAfter: this.disabledAfter,
          disabledBefore: this.disabledBefore,
        });
      }
    },
    getNextMonth(flag) {
      let currentMonth = this.moment(this.currentDate).add(1, "months").date(1);
      let daysOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).daysInMonth();

      let days = [];

      for (let i = 1; i <= daysOfMonth; i++) {
        // days.push(moment.date(i).format("YYYY-MM-DD"));
        let item = this.moment(currentMonth.format("YYYY-MM"), "YYYY-MM")
          .date(i)
          .format("YYYY-MM-DD");
        days.push(item);
        // console.log(currentMonth.date(i).format("YYYY-MM-DD"));
      }
      this.currentMonth = days;
      this.realDisplayInScreenData = this.currentMonth;

      let firstDayOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).date(1);
      let firstDayWeekDayOfMonth = firstDayOfMonth.isoWeekday();

      //   将本月1日前面的日期补充到数组中
      this.disabledBefore = [];
      for (let i = 1; i < firstDayWeekDayOfMonth; i++) {
        let disabledDate = this.moment(firstDayOfMonth.format("YYYY-MM-DD"))
          .subtract(i, "days")
          .format("YYYY-MM-DD");
        this.disabledBefore.unshift(disabledDate);
      }

      //   将本月最后一天的日期补充到数组中

      let lastDayOfMonth = this.moment(
        currentMonth.format("YYYY-MM"),
        "YYYY-MM"
      ).date(daysOfMonth);
      let lastDayWeekDayOfMonth = lastDayOfMonth.isoWeekday();
      this.disabledAfter = [];
      if (lastDayWeekDayOfMonth != 7) {
        for (let i = lastDayWeekDayOfMonth + 1; i <= 7; i++) {
          let disabledDate = this.moment(lastDayOfMonth.format("YYYY-MM-DD"))
            .isoWeekday(i, "days")
            .format("YYYY-MM-DD");
          this.disabledAfter.push(disabledDate);
        }
      }

      if (
        this.unKunowww.findIndex((item) => item.id === this.currentMonth[0]) ===
        -1
      ) {
        let lastCurrentIndex =
          this.unKunowww[this.unKunowww.length - 1].current;

        this.unKunowww.push({
          realDisplayInScreenData: this.currentMonth,
          id: this.currentMonth[0],
          current: flag ? flag : lastCurrentIndex + 1,
          disabledAfter: this.disabledAfter,
          disabledBefore: this.disabledBefore,
        });
      }
    },
    // 选中日期，灰色日期不可选择
    handleClose() {
      this.startDate = null;
      this.endDate = null;
      this.selectedDate = this.moment();
      // this.show = false;
    },
    handleOk() {
      if (this.startDate && this.endDate) {
        this.startDate = null;
        this.endDate = null;
        // 关闭日历组件
        this.show = false;
      }
    },
    changePage(v) {
      if (v < 1) return;
      if (!this.selectedMode) {
        this.selectedDate = v;
      }

      console.log(this.selectedMode);

      let date = this.markers.map((el) => el.date);
      if (date.includes(this.selectedDate.format("YYYY-MM-DD"))) {
        let item = this.markers.find(
          (el) => el.date == this.selectedDate.format("YYYY-MM-DD")
        );
        console.log(item);
      }

      this.$emit("change", v);

      // if(this.startDate&&v.isAfter(this.startDate)) {
      //   this.startDate = v
      //   return
      // }

      if (this.startDate && this.endDate) {
        if (v.isBefore(this.startDate)) {
          this.startDate = v;
        } else {
          this.endDate = v;

        }
      } else if (this.startDate) {
        this.endDate = this.moment(v);
        if (this.endDate.isBefore(this.startDate)) {
          let temp = this.moment(this.startDate);
          this.startDate = this.moment(this.endDate);
          this.endDate = this.moment(temp);
        }
      } else {
        this.startDate = this.moment(v);
      }

      // this.resetStartWeekEndWeek()

      // let self = this;
      // const query = uni.createSelectorQuery().in(this);
      // let headerBottom = 0;
      // query
      //   .select("#header")
      //   .boundingClientRect((headerData) => {
      //     console.log("得到header的布局位置信息" + JSON.stringify(headerData));
      //     headerBottom = headerData.bottom;
      //   })
      //   .exec();

      // query
      //   .select(
      //     "#" +
      //       "test" +
      //       self.currentDate.format("YYYY-MM-DD").replaceAll("-", "")
      //   )
      //   .boundingClientRect((data) => {
      //     console.log("得到布局位置信息" + JSON.stringify(data));
      //     console.log("节点离页面顶部的距离为" + data.top);
      //     self.marginTop = -(data.top - headerBottom);

      //     console.log(self.marginTop, uni.upx2px(self.marginTop));
      //   })
      //   .exec();
    },
    resetStartWeekEndWeek() {
      this.startOfWeek = this.moment(this.selectedDate).startOf("isoWeek");
      this.endOfWeek = this.moment(this.selectedDate).endOf("isoWeek");
    },
    // 阻止默认事件
    transformShape($event) {
      $event.preventDefault();
    },
    // 触摸开始事件
    transformStart($event) {
      // alert(123)
      this.position.start = $event.changedTouches[0].clientY;
    },
    // 向上/下 滑动日历组件触发的事件
    transformEnd($event) {
      this.position.end = $event.changedTouches[0].clientY;
      let distance = this.position.end - this.position.start;
      if (distance > 100) {
        // this.current = 0;
        let temo = [
          this.unKunowww[0].current,
          this.unKunowww[1].current,
          this.unKunowww[2].current,
        ];
        this.unKunowww = [];
        this.getCurrentMonth(temo[1]);
        this.getNextMonth(temo[2]);
        this.getPreMonth(temo[0]);
        this.mode = "month";
        this.$emit("forwardup");
      }
      if (distance < -100) {
        // this.current = 0;
        let temo = [
          this.unKunowww[0].current,
          this.unKunowww[1].current,
          this.unKunowww[2].current,
        ];
        this.unKunowww = [];
        this.getCurrentWeeks(temo[1]);
        this.getPreWeeks(temo[0]);
        this.getNextWeeks(temo[2]);
        this.mode = "week";
        this.$emit("forwarddown");
      }
      console.log(this.current);

      // this.page = 0
    },
    transformSwiperStart($event) {
      this.position.swiperStart = $event.changedTouches[0].clientX;
    },
    transformSwiperEnd($event) {
      this.position.swiperEnd = $event.changedTouches[0].clientX;
      let distance = this.position.swiperEnd - this.position.swiperStart;

      if (distance > 100) {
        this.preWeek();
        this.$emit("forwardleft");
      }
      if (distance < -100) {
        this.nextWeek();
        this.$emit("forwardright");
      }
      console.log(this.current);
    },
    transformSwiper() {},
    // 上一周/月
    preWeek() {
      if (this.mode == "week") {
        this.currentDate.subtract(1, "weeks");
        // this.getCurrentWeeks();
        this.unKunowww.pop();
        this.getPreWeeks();
        this.current++;
      } else {
        this.currentDate.subtract(1, "months");
        // this.getCurrentMonth();
        this.unKunowww.pop();
        this.getPreMonth();

        this.current++;
      }
      this.$emit("prepage", this.current, this.currentDate);
    },
    // 下一周/月
    nextWeek() {
      if (this.mode == "week") {
        this.currentDate.add(1, "weeks");
        // this.getCurrentWeeks();
        this.unKunowww.shift();
        this.getNextWeeks();
        this.current--;
      } else {
        this.currentDate.add(1, "months");
        // this.getCurrentMonth();
        this.unKunowww.shift();
        this.getNextMonth();
        this.current--;
      }
      this.$emit("nextpage", this.current, this.currentDate);
    },
    // 重置组件参数
    reset() {
      this.unKunowww = [];
      this.current = 0;
      this.selectedDate = this.moment();
      this.currentDate = this.selectedDate; // 修改
      if (this.mode == "week") {
        this.getCurrentWeeks();
        this.getPreWeeks();
        this.getNextWeeks();
      } else {
        this.getCurrentMonth();
        this.getPreMonth();
        this.getNextMonth();
      }
      this.$emit("reset", this.selectedDate, this.currentDate, this.current);
      this.resetStartWeekEndWeek();
    },
    // 显示日历
    open() {
      this.selectedMode = true;
      this.show = !this.show;
      this.$emit("open");
    },
    open1() {
      this.selectedMode = false;
      this.show = !this.show;
      this.$emit("open");
    },
    checkIfShow(item) {
      let date = this.markers.map((el) => el.date);
      return date.includes(item);
    },
    markerColor(item) {
      let color = this.markers.find((el) => el.date == item).color;
      return color;
    },
  },
};
</script>

<style>
@import "@/plugin/colorui/common.less";
.selected {
  background-color: purple !important;
  color: white;
}

.today {
  background-color: #0081ff;
  color: white;
}
.calendar-body {
  transition: all 0.3s ease-in-out;
  overflow: hidden;
}

.swiper {
  position: relative;
  min-height: 90rpx;
  height: 90rpx;
  width: 750rpx;
  transition: all 0.5s ease-in-out;
}
.swiper-item {
  position: absolute;
  left: 0;
  width: 710rpx;
  height: 90rpx;
  min-height: 90rpx;
  display: block;
  line-height: auto;
  text-align: center;
}
.calendar-item {
  position: relative;
}
.point {
  position: absolute;
  width: 10rpx;
  height: 10rpx;
  background: lawngreen;
  border: 1px solid black;
  left: 50%;
  border-radius: 100%;
  transform: translateX(-50%);
  bottom: 10rpx;
}

.ranged {
  background-color: white;
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.3);
  color: black;
}
.start {
  background: #0081ff;
  color: white;
}
.end {
  background: #0081ff;
  color: white;
}
</style>
